﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;

using UnityEngine;
using DashFire;

namespace DashFire
{
  public class ResUpdateControler
  {
    public static ResUpdateError s_UpdateError = ResUpdateError.None;
    public static VersionInfo s_BuildinClientVersionInfo;
    public static VersionInfo s_PerszistClientVersionInfo;
    public static VersionInfo s_ClientVersionInfo;
    public static VersionInfo s_ServerVersionInfo;

    public static string s_ChannelName = "orange";
    public static bool s_IsNeedUpdate;
    public static bool s_IsNeedPauseUpdate;
    public static int s_DownLoadNum;
    public static bool s_IsNeedSyncPackage;
    public static int s_ReconnectNum;
    public static bool s_IsTestClientVersion;
    public static bool s_IsShowUpdateResTip = false;
    public static bool s_IsShowUpdateResTipInGame = true;
    public static bool s_IsShowUpdateTipInGame;
    public static bool s_IsFinishedUpdate = false;

    public static AssetBundle s_CurSceneAssetbundle = null;
    public static List<string> s_SheetZipList = new List<string>();
    public static Dictionary<string, AssetBundle> s_SharedAssetbundle = new Dictionary<string, AssetBundle>();

    #region Update Sequence
    public static bool InitContext()
    {
      //ResUpdateHandler.HandleStartCoroutine = ResUpdateTool.StartCoroutineImpl;
      //ResUpdateHandler.HandleIsResPackaged = ResLoadHelper.IsResAssetCached;
      //ResUpdateHandler.HandleLoadLevelAsync = ResLevelLoader.LoadLevelAsync;
      //ResUpdateHandler.HandleLoadResource = ResUpdateTool.LoadCachedAsset;
      //ResUpdateHandler.HandleLoadResourceAsync = ResUpdateTool.LoadCachedAssetAsync;
      //ResUpdateHandler.HandlePreloadResByLevel = ResLevelLoader.PreloadResAssetByLevel;
      ////ResUpdateHandler.HandlePreloadResByLevel = ResLevelLoader.PreloadResAssetByLevel;
      //ResUpdateHandler.HandleClean = Clean;
      s_IsFinishedUpdate = false;
      return true;
    }
    public static void InitUpdate()
    {
      s_IsNeedUpdate = false;
      s_IsNeedPauseUpdate = false;
      s_DownLoadNum = 0;
      s_UpdateError = ResUpdateError.None;
      s_IsTestClientVersion = false;
      s_IsShowUpdateTipInGame = false;
      s_SheetZipList.Clear();
    }
    public static ResAsyncInfo StartUpdate()
    {
      ResAsyncInfo info = new ResAsyncInfo();
      info.CurCoroutine = CoroutineProxy.Instance.StartCoroutine(ResUpdateControlerHandler.StartUpdate(info));
      return info;
    }
    public static void ExitUpdate()
    {
      s_IsNeedUpdate = false;
      s_DownLoadNum = 0;
      s_UpdateError = ResUpdateError.None;
      s_IsFinishedUpdate = true;
    }
    public static void Clean()
    {
      if (s_CurSceneAssetbundle != null) {
        s_CurSceneAssetbundle.Unload(false);
        s_CurSceneAssetbundle = null;
      }
      foreach (AssetBundle ab in s_SharedAssetbundle.Values) {
        ab.Unload(true);
      }
      s_SharedAssetbundle.Clear();
    }
    internal static ResAsyncInfo DetectVersion()
    {
      ResAsyncInfo info = new ResAsyncInfo();
      info.CurCoroutine = CoroutineProxy.Instance.StartCoroutine(ResUpdateControlerHandler.DetectVersion(info));
      return info;
    }
    internal static ResAsyncInfo DetectVersionInGame()
    {
      ResAsyncInfo info = new ResAsyncInfo();
      info.CurCoroutine = CoroutineProxy.Instance.StartCoroutine(ResUpdateControlerHandler.DetectVersionInGame(info));
      return info;
    }
    internal static void UpdateVersionInfo()
    {
      VersionNum cVersionNum = s_ClientVersionInfo.Version;
      string versionInfo = string.Format(ResUpdateConfig.s_VersionInfoFormat,
            cVersionNum.AppChannel, cVersionNum.AppMaster, cVersionNum.ResBase, (double)(CodeVersion.Value));
      LogicForGfxThread.UpdateVersinoInfo(versionInfo);
      ResLoadHelper.Log("OnUpdateVersionInfo:" + versionInfo);
      ResUpdateCallback.OnUpdateVersionNum(versionInfo);
    }
    #endregion

    #region Update Callback
    internal static void OnUpdateCompleted(bool isdownload)
    {
      if (isdownload && s_ServerVersionInfo != null) {
        string versionNum = s_ServerVersionInfo.Version.GetVersionStr();
        s_ClientVersionInfo.Version = new VersionNum(versionNum);
        s_ClientVersionInfo.Save();

        s_ClientVersionInfo.Save();
        if (s_DownLoadNum > 0) {
          ResVersionLoader.SaveClientResVersion();
          s_DownLoadNum = 0;
        }
        UpdateVersionInfo();
      }
      s_ReconnectNum = 0;
      s_IsNeedSyncPackage = false;
    }
    internal static void OnForceDownload(int selected)
    {
      OnForceDownload(true);
    }
    internal static void OnForceDownload(bool selected)
    {
      string downloadUrl = string.Empty;
      if (!string.IsNullOrEmpty(ChannelConfig.s_ForceDownloadUrl)) {
        downloadUrl = ChannelConfig.s_ForceDownloadUrl;
      } else if (s_ServerVersionInfo != null) {
        downloadUrl = s_ServerVersionInfo.ForceDownloadURL;
        downloadUrl = downloadUrl.Replace("[group]", GameConfig.s_GroupName);
        downloadUrl = downloadUrl.Replace("[channel]", GameConfig.s_ChannelName);
      }

#if UNITY_APPSTORE
      if (string.IsNullOrEmpty(downloadUrl)) {
        downloadUrl = "https://itunes.apple.com/cn/app/id955307313";
      }
#endif
      if (!string.IsNullOrEmpty(downloadUrl)) {
        ResLoadHelper.Log("OnForceDownload:" + downloadUrl);
        Application.OpenURL(downloadUrl);
        Application.Quit();
      }
    }
    internal static void OnUpdateRes(bool selected)
    {
      ResUpdateControler.s_IsNeedPauseUpdate = false;
      if (selected) {
        ResUpdateControler.s_IsNeedUpdate = true;
      } else {
        ResUpdateControler.s_IsNeedUpdate = false;
      }
    }
    internal static void OnTipUpdate(bool selected)
    {
      ResUpdateControler.s_IsShowUpdateTipInGame = true;
    }
    internal static void OnFinishExtractInnerRes()
    {
      ResUpdateControler.s_ClientVersionInfo.IsResInnerConfigCached = true;
      ResUpdateControler.s_ClientVersionInfo.Save();
    }
    #endregion

  }
  /// <summary>
  /// Unity 4.2.2不支持在dll的类中混合IEnumerator和普通函数, 
  /// 因此，将包含yield的函数分离开来，by lixiaojiang
  /// Bug:http://lists.ximian.com/pipermail/mono-bugs/2011-July/112237.html
  /// </summary>
  internal class ResUpdateControlerHandler
  {
    internal static IEnumerator StartUpdate(ResAsyncInfo info)
    {
      ResVersionLoader.LoadClientResVersion();

      if (!ResUpdateControler.s_ClientVersionInfo.IsResInnerConfigCached) {
        LogicForGfxThread.UpdateLoadingProgress(0.1f);
        yield return 1;

        // Prepare inner res
        ResAsyncInfo loadInnerResVersionInfo = ResVersionInnerLoader.LoadInnerResVersion();
        yield return loadInnerResVersionInfo.CurCoroutine;
        if (loadInnerResVersionInfo.IsError) {
          ResLoadHelper.Log("加载内置表格资源列表错误");
          info.IsError = true;
          yield break;
        }
        ResAsyncInfo loadInnerResInfo = ResVersionInnerLoader.StartLoad();
        if (loadInnerResInfo.CurCoroutine != null) {
          yield return loadInnerResInfo.CurCoroutine;
        }
        if (loadInnerResInfo.IsError) {
          ResLoadHelper.Log("解压内置资源错误");
          info.IsError = true;
          yield break;
        }
        ResVersionInnerLoader.OnFinishExtractResInner();

        // Extract sheet res
        LogicForGfxThread.UpdateLoadingProgress(0.5f);
        yield return 1;

        ResAsyncInfo loadResSheetInfo = ResSheetLoader.LoadResSheet();
        yield return loadResSheetInfo.CurCoroutine;
        if (loadResSheetInfo.IsError) {
          ResLoadHelper.Log("加载表格资源列表错误");
          info.IsError = true;
          yield break;
        }
        ResAsyncInfo extractResSheetInfo = ResSheetLoader.ExtractResSheet(string.Format(ResUpdateConfig.s_ResSheetZipFormat, ""), false);
        if (extractResSheetInfo.CurCoroutine != null) {
          yield return extractResSheetInfo.CurCoroutine;
        }
        if (extractResSheetInfo.IsError) {
          ResLoadHelper.Log("解压表格资源列表错误");
          info.IsError = true;
          yield break;
        }
        ResSheetLoader.OnFinishExtractResSheetZip();
        ResUpdateControler.OnFinishExtractInnerRes();
        ResUpdateControler.OnUpdateCompleted(false);
      }

      if (ResUpdateControler.s_IsNeedUpdate) {
        ResUpdateCallback.OnStartUpdate();

        LogicForGfxThread.UpdateLoadingProgress(0.0f);
        yield return 1;
        ResAsyncInfo requestPackageInfo = ResPackageLoader.RequestResPackage();
        yield return requestPackageInfo.CurCoroutine;
        if (requestPackageInfo.IsError) {
          ResLoadHelper.Log("请求更新包信息错误");
          info.IsError = true;
          yield break;
        }

        ResAsyncInfo startDownloadInfo = ResDownLoader.StartDownload();
        yield return startDownloadInfo.CurCoroutine;
        if (startDownloadInfo.IsError) {
          ResLoadHelper.Log("更新资源错误");
          info.IsError = true;
          //yield break;
        } else {
          LogicForGfxThread.UpdateLoadingProgress(1.0f);
          yield return 1;
          ResUpdateControler.OnUpdateCompleted(true);
          ResUpdateCallback.OnEndUpdate();
        }
      }
      
      LogicForGfxThread.UpdateLoadingProgress(1.0f);
      info.Progress = 1.0f;
      info.IsDone = true;
    }
    internal static IEnumerator DetectVersion(ResAsyncInfo info)
    {
      ResUpdateCallback.OnStartDetectVersion();
      string tip = Dict.Get("StrDictionary_String_26");
      if (string.IsNullOrEmpty(tip)) {
#if LANG_KR
        tip = "버전 확인 중...";
#elif LANG_CHT
        tip = "版本檢測中…";
#else
        tip = "版本检测中…";
#endif
      }
      LogicForGfxThread.UpdateLoadingTip(tip);

      ResAsyncInfo loadClientVersionInfo = VersionLoader.RequestClientVersion();
      yield return loadClientVersionInfo.CurCoroutine;
      if (loadClientVersionInfo.IsError) {
        UnityEngine.Debug.Log("加载客户端版本信息错误");
        info.IsError = true;
        yield break;
      }

      //LogicForGfxThread.UpdateLoadingProgress(0, "加载服务器版本...");
      ResAsyncInfo requestServerVersionInfo = VersionLoader.RequestServerVersion();
      yield return requestServerVersionInfo.CurCoroutine;
      if (requestServerVersionInfo.IsError) {
        ResLoadHelper.Log("加载服务器版本错误，跳过...");
      }

      ResAsyncInfo requestChannelConfigInfo = ChannelConfigLoader.RequestChannelConfig();
      yield return requestChannelConfigInfo.CurCoroutine;
      if (requestChannelConfigInfo.IsError) {
        UnityEngine.Debug.Log("获取渠道配置信息错误，可能无需配置");
      }

      if (ResUpdateControler.s_ServerVersionInfo != null
        && ResUpdateControler.s_ClientVersionInfo != null) {
        VersionNum serverVersionNum = ResUpdateControler.s_ServerVersionInfo.Version;
        VersionNum clientVersionNum = ResUpdateControler.s_ClientVersionInfo.Version;
        ResUpdateControler.s_IsNeedPauseUpdate = false;

        ResLoadHelper.Log(string.Format("ClientVersion:{0} ServerVersion:{1}",
          clientVersionNum.GetVersionStr(), serverVersionNum.GetVersionStr()));

        ResUpdateControler.s_IsNeedUpdate = false;
        if (clientVersionNum.GetAppVersionForceValue() < serverVersionNum.GetAppVersionForceValue()) {
          string tipInfo = string.Format("有新版本可更新，版本号：" + serverVersionNum.GetVersionStr());
          ResLoadHelper.Log(tipInfo);

          if (ChannelConfig.s_IsShowConformTip) {
            ResUpdateControler.s_IsNeedPauseUpdate = true;

            Action<bool> fun = ResUpdateControler.OnForceDownload;
            string dlgTip = Dict.Get("StrDictionary_String_6");
            if (string.IsNullOrEmpty(dlgTip)) {
#if LANG_KR
              dlgTip = "업데이트를 해주세요";
#elif LANG_CHT
              dlgTip = "版本过旧，你需要更新一下";
#else
              dlgTip = "版本过旧，你需要更新一下";
#endif
            }
            string dlgButton = Dict.Get("StrDictionary_String_81");
            if (string.IsNullOrEmpty(dlgButton)) {
#if LANG_KR
              dlgButton = "#N/A";
#elif LANG_CHT
              dlgButton = "更新";
#else
              dlgButton = "更新";
#endif
            }
            DashFire.LogicForGfxThread.EventForGfx.Publish("ge_show_yesornot", "ui", dlgTip, dlgButton, fun);
          }
        } else if (clientVersionNum.GetAppVersionForceValue() == serverVersionNum.GetAppVersionForceValue()) {
          if (clientVersionNum.GetResVersionValue() < serverVersionNum.GetResVersionValue()) {
            //LogicForGfxThread.UpdateLoadingProgress(0, );
            ResLoadHelper.Log("检测到有资源需要更新:" + serverVersionNum.GetVersionStr());
            if (ResUpdateControler.s_IsShowUpdateResTip) {
              ResUpdateControler.s_IsNeedPauseUpdate = true;
              Action<bool> fun = ResUpdateControler.OnUpdateRes;
              string dlgTip = Dict.Get("StrDictionary_String_6");
              if (string.IsNullOrEmpty(dlgTip)) {
#if LANG_KR
                dlgTip = "업데이트를 해주세요";
#elif LANG_CHT
                dlgTip = "版本过旧，你需要更新一下";
#else
                dlgTip = "版本过旧，你需要更新一下";
#endif
              }
              string leftButton = Dict.Get("StrDictionary_String_81");
              if (string.IsNullOrEmpty(leftButton)) {
#if LANG_KR
                leftButton = "#N/A";
#elif LANG_CHT
                leftButton = "更新";
#else
                leftButton = "更新";
#endif
              }
              string rightButton = Dict.Get("StrDictionary_String_10");
              if (string.IsNullOrEmpty(rightButton)) {
#if LANG_KR
                rightButton = "취소";
#elif LANG_CHT
                rightButton = "取消";
#else
                rightButton = "取消";
#endif
              }
              DashFire.LogicForGfxThread.EventForGfx.Publish("ge_show_confirmdlg", "ui", dlgTip, leftButton, rightButton, fun);
            } else {
              ResUpdateControler.s_IsNeedUpdate = true;
            }
          } else {
            ResLoadHelper.Log("已经是最新版本:" + serverVersionNum.GetVersionStr());
            //LogicForGfxThread.UpdateLoadingProgress(0, "已经是最新版本:" + serverVersionNum.GetVersionStr());
          }
        } else {
          ResLoadHelper.Log("客户端版本高于服务器版本:" + serverVersionNum.GetVersionStr());
          ResLoadHelper.Log("客户端为测试客户端包，服务器列表将使用ServerConfig_new.txt:");
          ResUpdateControler.s_IsTestClientVersion = true;
        }
        ResUpdateCallback.OnEndDetectVersion(ResUpdateControler.s_IsNeedUpdate);
      } else {
        ResLoadHelper.Log("客户端或服务器版本号丢失.");
      }

      info.IsDone = true;
      info.Progress = 1.0f;
    }
    internal static IEnumerator DetectVersionInGame(ResAsyncInfo info)
    {
      //LogicForGfxThread.UpdateLoadingProgress(0, "加载服务器版本...");
      ResAsyncInfo requestServerVersionInfo = VersionLoader.RequestServerVersion();
      yield return requestServerVersionInfo.CurCoroutine;
      if (requestServerVersionInfo.IsError) {
        ResLoadHelper.Log("加载服务器版本错误，跳过...");
      }
      if (ResUpdateControler.s_ServerVersionInfo != null
        && ResUpdateControler.s_ClientVersionInfo != null) {
        VersionNum serverVersionNum = ResUpdateControler.s_ServerVersionInfo.Version;
        VersionNum clientVersionNum = ResUpdateControler.s_ClientVersionInfo.Version;

        ResLoadHelper.Log(string.Format("ClientVersion:{0} ServerVersion:{1}",
          clientVersionNum.GetVersionStr(), serverVersionNum.GetVersionStr()));

        if (clientVersionNum.GetAppVersionForceValue() < serverVersionNum.GetAppVersionForceValue() && false) {
          string tipInfo = string.Format("有新版本可更新，版本号：" + serverVersionNum.GetVersionStr());
          ResLoadHelper.Log(tipInfo);

          if (ChannelConfig.s_IsShowConformTip) {
            Action<bool> fun = ResUpdateControler.OnTipUpdate;
            string dlgTip = Dict.Get("StrDictionary_String_73");
            if (string.IsNullOrEmpty(dlgTip)) {
#if LANG_KR
              dlgTip = "#N/A";
#elif LANG_CHT
              dlgTip = "版本过旧，请重启游戏，遵循提示进行更新操作";
#else
              dlgTip = "版本过旧，请重启游戏，遵循提示进行更新操作";
#endif
            }
            string dlgButton = Dict.Get("StrDictionary_String_5");
            if (string.IsNullOrEmpty(dlgButton)) {
#if LANG_KR
              dlgTip = "확인";
#elif LANG_CHT
              dlgButton = "确定";
#else
              dlgButton = "确定";
#endif
            }
            DashFire.LogicForGfxThread.EventForGfx.Publish("ge_show_yesornot", "ui", dlgTip, dlgButton, fun);
          }
        } else if (clientVersionNum.GetAppVersionForceValue() == serverVersionNum.GetAppVersionForceValue()) {
          if (clientVersionNum.GetResVersionValue() < serverVersionNum.GetResVersionValue()) {
            //LogicForGfxThread.UpdateLoadingProgress(0, );
            ResLoadHelper.Log("检测到有资源需要更新:" + serverVersionNum.GetVersionStr());
            if (ResUpdateControler.s_IsShowUpdateResTipInGame) {
              Action<bool> fun = ResUpdateControler.OnTipUpdate;
              string dlgTip = Dict.Get("StrDictionary_String_73");
              if (string.IsNullOrEmpty(dlgTip)) {
#if LANG_KR
                dlgTip = "#N/A";
#elif LANG_CHT
                dlgTip = "版本过旧，请重启游戏，遵循提示进行更新操作";
#else
                dlgTip = "版本过旧，请重启游戏，遵循提示进行更新操作";
#endif
              }
              string leftButton = Dict.Get("StrDictionary_String_5");
              if (string.IsNullOrEmpty(leftButton)) {
#if LANG_KR
                leftButton = "확인";
#elif LANG_CHT
                leftButton = "确定";
#else
                leftButton = "确定";
#endif
              }
              DashFire.LogicForGfxThread.EventForGfx.Publish("ge_show_yesornot", "ui", dlgTip, leftButton, fun);
            }
          } else {
            ResLoadHelper.Log("已经是最新版本:" + serverVersionNum.GetVersionStr());
            //LogicForGfxThread.UpdateLoadingProgress(0, "已经是最新版本:" + serverVersionNum.GetVersionStr());
          }
        } else {
          ResLoadHelper.Log("客户端版本高于服务器版本:" + serverVersionNum.GetVersionStr());
          ResLoadHelper.Log("客户端为测试客户端包，服务器列表将使用ServerConfig_new.txt:");
        }
      } else {
        ResLoadHelper.Log("客户端或服务器版本号丢失.");
      }

      info.IsDone = true;
      info.Progress = 1.0f;
    }
  }
}